package com.versiFramework.controller{

	import com.versiFramework.events.versiEvent;
	import com.versiFramework.core.ctrlEvent;
	import com.versiFramework.versi;
	import com.versiFramework.views.popups.extAlert;
	import com.versiFramework.core.IController;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.EventDispatcher;
	import flash.geom.Point;
	import flash.utils.ByteArray;
	
	import mx.controls.Alert;
	import mx.core.IFlexDisplayObject;
	import mx.managers.PopUpManager;
	import mx.utils.ObjectUtil;
		
	public class versiController extends EventDispatcher implements IController {

		private var _name:String;
		
		public function get name():String
		{
			return this._name;
		}	
				
		private function get dispatcher():versi
		{
			return versi.getInstance();
		}
		
		public function get versiVersion():String
		{
			return versi.VERSION;
		}

		protected function addListeners():void
		{
			dispatcher.addEventListener(name, onCtrlEvent,false,0,true);
			dispatcher.addEventListener(versi.CTRL_ALL, onCtrlEvent,false,0,true);
		}
		
		protected function removeListeners():void
		{
			dispatcher.removeEventListener(name, onCtrlEvent);
			dispatcher.removeEventListener(versi.CTRL_ALL, onCtrlEvent);
		}
		
		//####################################################
		//	utility methods
		//####################################################

		public function clone(source:Object):*
		{
		    var myBA:ByteArray = new ByteArray();
		    myBA.writeObject(source);
		    myBA.position = 0;
		    return(myBA.readObject());
		}
		
		public function objectAppend(source1:Object,source2:Object,overwrite:Boolean=true,clone:Boolean=false):Object
		{
		    var obj1:Object;
		    var obj2:Object;
		    
		    if (!clone)
		    {
		    	obj1=source1;
		    	obj2=source2;
		    }
		    else
		    {
		    	obj1=this.clone(source1);
		    	obj2=this.clone(source2);
		    }
		    
		    for (var itemName:String in obj2)
		    {
		    	if (overwrite || ! obj1.hasOwnProperty(itemName))
		    	{
		    		obj1[itemName] = obj2[itemName];
		    	}
		    }
		    return obj1
		}
		
		public function serializeObject(someObject:Object):ByteArray
		{
			var objectBytes:ByteArray = new ByteArray();
			objectBytes.writeObject(someObject);
			return objectBytes;
		}
		
		public function deserializeObject(someByteArray:ByteArray):*
		{
			if (someByteArray)
			{
				var sdObject:* =  someByteArray.readObject();
				return sdObject;
			} else { return null }
		}
		
		public function objectLen(o:Object):uint
		{
			var len:uint = 0;
			for (var item:* in o)
				if (item != "mx_internal_uid")
					len++;
			return len;
		}
		
		public function xmlDeleteNode(xmlToDelete:XML):void
		{
			delete xmlToDelete.parent().children()[ xmlToDelete.childIndex() ];
		}
		
		public function doPopup(popup:IFlexDisplayObject,parent:DisplayObject,modal:Boolean=true,posX:int=-1,posY:int=-1):void		{
			PopUpManager.addPopUp(popup, parent , modal);
			if (posX != -1 )
			{
				popup.x=posX;
				popup.y=posY;
			}
			else
			{
				PopUpManager.centerPopUp(popup);
			}
		}
		
		public function removePopup(popup:IFlexDisplayObject):void
		{
			PopUpManager.removePopUp(popup);
		}
		
		public function centerPopUp(popUp:IFlexDisplayObject):void
		{
			var pt:Point = new Point(0, 0);
			pt = popUp.parent.localToGlobal(pt);
			pt = popUp.parent.globalToLocal(pt);
			popUp.move(Math.round((popUp.parent.width - popUp.width) / 2) + pt.x,
			Math.round((popUp.parent.height - popUp.height) / 2) + pt.y);
		}
		
		public function alertText(source:String, win:DisplayObject):void
		{
			if (source.length < 750)
			{
				Alert.show(source,null,4,win as Sprite);
			}
			else
			{
				var newAlert:extAlert= new extAlert;
				newAlert.init(source);
				this.doPopup(newAlert,win,true);
			}
		}
		
		public function alertObject(source:*, win:DisplayObject):void
		{
			alertText(ObjectUtil.toString(source),win);
		}
		



		//####################################################
		//	event manager
		//####################################################
		/* rebroadcast the versi & content events to content subscribers */
		private function onCtrlEvent(evt:ctrlEvent):void
		{
			doEvent(evt.msg,evt.data);
		}

		public function doEvent(type:String,data:*=null,target:*=null):void
		{
			if (target == null || (target is String && target == this.name))
			{	this.dispatchEvent( new versiEvent(type,data) );	}
			else if (target is DisplayObject)
			{	target.dispatchEvent( new versiEvent(type,data,true,true) ); }
			else
			{ versi.doEvent(type,data,target); } 	
		}
		
		public function doFunction(fun:String,args:Array=null,target:String=null):*
		{
			if (target == null || target == name)
			{
				if (this.hasOwnProperty(fun))
				{
					return this[fun].apply(null,args);
				}
				
			}
			else
			{
				return this.dispatcher.doFunction(target,fun,args)
			}
		}

		public function versiController(name:String){
			_name = name;
			addListeners();
		}


	}
}